package net.esj.basic.dao.querybuilder;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import net.esj.basic.core.engine.annotation.Ignore;
import net.esj.basic.dao.hibernate.HibernateQueryBuilder;
import net.esj.basic.exception.MelonException;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * QB工厂 请用该工厂创建queryBuilder 以后版本将取消显式创建QB
 * @author Administrator
 *
 */
public class QueryBuilderFactory implements InitializingBean,ApplicationContextAware{
	
	private static Class defaultQb = HibernateQueryBuilder.class;
	
	private String defaultQueryBuilder = HibernateQueryBuilder.class.getName();

	private ApplicationContext applicationContext;
	
	private static Set<String> needMethods = new HashSet<String>();
	static{
		Method[] methods= QueryBuilder.class.getMethods();
		for(Method m: methods){
			needMethods.add(m.getName());
		}
	}
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}
	
	public static QueryBuilder create(Class<?> tc){
		try {
			return create(defaultQb, tc);
		} catch (Exception e) {
			throw new MelonException("不能从工厂中创建该QB",e);
		}
	}
	
	public static QueryBuilder create(Class<?> qbclass,Class<?> tc){
		if(!QueryBuilder.class.isAssignableFrom(qbclass)){
			throw new IllegalArgumentException("类型不匹配,qbclass必须是QueryBuilder的子类");
		}
		try {
			//QueryBuilder qb = (QueryBuilder) qbclass.getConstructor(new Class[]{Class.class}).newInstance(tc);
			Enhancer enhancer = new Enhancer(); 
			enhancer.setSuperclass(qbclass);
			enhancer.setCallback(new MethodInterceptor() {
			
				@SuppressWarnings("unchecked")
				@Override
				public Object intercept(Object obj, Method method, Object[] args,
						MethodProxy proxy) throws Throwable {
					if(!method.isAnnotationPresent(Ignore.class)
							&&needMethods.contains(method.getName())){
						((AbstractQueryBuilder)obj).record(method, args);
					}
					return proxy.invokeSuper(obj, args);
				}
			});
			return (QueryBuilder)enhancer.create(new Class[]{Class.class},new Object[]{tc});
		} catch (Exception e) {
			throw new MelonException("不能从工厂中创建该QB",e);
		}
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		defaultQb = Class.forName(defaultQueryBuilder);
		if(!defaultQb.isAssignableFrom(QueryBuilder.class)){
			throw new IllegalArgumentException("类型不匹配,defaultQueryBuilder必须是QueryBuilder的子类");
		}
	}

	public void setDefaultQueryBuilder(String defaultQueryBuilder) {
		this.defaultQueryBuilder = defaultQueryBuilder;
	}

}
